package com.example.hotel.blImpl.hotel;

import com.example.hotel.bl.hotel.RoomRepoService;
import com.example.hotel.bl.hotel.RoomService;
import com.example.hotel.bl.order.OrderService;
import com.example.hotel.data.hotel.RoomRepoMapper;
import com.example.hotel.enums.RoomType;
import com.example.hotel.po.HotelDateCntPO;
import com.example.hotel.po.HotelRoom;
import com.example.hotel.po.RoomRepoPO;
import com.example.hotel.po.RoomTypeDetailVO;
import com.example.hotel.vo.DatePeriodVO;
import com.example.hotel.vo.DateRoomRepoVO;
import com.example.hotel.vo.ResponseVO;
import com.example.hotel.vo.RoomTypeUpdateVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class RoomRepoServiceImpl implements RoomRepoService {
    @Autowired
    RoomRepoMapper roomRepoMapper;

    @Autowired
    RoomService roomService;

    @Autowired
    OrderService orderService;

    DateTimeFormatter formatterFull = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    DateTimeFormatter formatterDay = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public Map<String, Integer> getForPeriod(DatePeriodVO datePeriodVO) {
        LocalDateTime fromDate = LocalDateTime.parse(datePeriodVO.getFromDate()+" 00:00:00", formatterFull);
        LocalDateTime toDate = LocalDateTime.parse(datePeriodVO.getToDate()+" 00:00:00", formatterFull);
        Map<String, Integer> periodInfo = new HashMap<>();

        // 格式验证
        if (toDate.isBefore(fromDate)) return periodInfo;

        // 计算
        while (!fromDate.isAfter(toDate)) {
            RoomRepoPO roomRepoPO = new RoomRepoPO();
            String dateStr = fromDate.format(formatterDay);
            roomRepoPO.setRoomId(datePeriodVO.getRoomId());
            roomRepoPO.setDate(dateStr);

            List<RoomRepoPO> roomRepoPOS = roomRepoMapper.searchRoom(roomRepoPO);

            if (roomRepoPOS.size() == 0) periodInfo.put(dateStr, 0);
            else periodInfo.put(dateStr, roomRepoPOS.get(0).getCurrentNum());
            fromDate = fromDate.plusDays(1);
        }

        return periodInfo;
    }

    @Override
    public List<DateRoomRepoVO> getForPeriodList(DatePeriodVO datePeriodVO) {
        LocalDateTime fromDate = LocalDateTime.parse(datePeriodVO.getFromDate()+" 00:00:00", formatterFull);
        LocalDateTime toDate = LocalDateTime.parse(datePeriodVO.getToDate()+" 00:00:00", formatterFull);
        List<DateRoomRepoVO> dList = new LinkedList<>();

        // 格式验证
        if (toDate.isBefore(fromDate)) return dList;

        // 计算
        while (!fromDate.isAfter(toDate)) {
            RoomRepoPO roomRepoPO = new RoomRepoPO();
            String dateStr = fromDate.format(formatterDay);
            roomRepoPO.setRoomId(datePeriodVO.getRoomId());
            roomRepoPO.setDate(dateStr);

            List<RoomRepoPO> roomRepoPOS = roomRepoMapper.searchRoom(roomRepoPO);

            DateRoomRepoVO dateRoomRepoVO = new DateRoomRepoVO();

            if (roomRepoPOS.size() == 0) {
                dateRoomRepoVO.setDate(dateStr);
                dateRoomRepoVO.setEmptyRoomCnt(0);
                dList.add(dateRoomRepoVO);
            }
            else {
                dateRoomRepoVO.setDate(dateStr);
                dateRoomRepoVO.setEmptyRoomCnt(roomRepoPOS.get(0).getCurrentNum());
                dList.add(dateRoomRepoVO);
            }
            fromDate = fromDate.plusDays(1);
        }

        return dList;
    }

    @Override
    public Boolean setForPeriod(DatePeriodVO datePeriodVO) {
        LocalDateTime fromDate = LocalDateTime.parse(datePeriodVO.getFromDate()+" 00:00:00", formatterFull);
        LocalDateTime toDate = LocalDateTime.parse(datePeriodVO.getToDate()+" 00:00:00", formatterFull);
        Map<String, Integer> periodInfo = new HashMap<>();

        // 格式验证
        if (toDate.isBefore(fromDate)) return false;

        // 计算
        while (!fromDate.isAfter(toDate)) {
            RoomRepoPO roomRepoPO = new RoomRepoPO();
            String dateStr = fromDate.format(formatterDay);
            roomRepoPO.setRoomId(datePeriodVO.getRoomId());
            roomRepoPO.setDate(dateStr);
            roomRepoPO.setCurrentNum(datePeriodVO.getValToSet());

            if (roomRepoMapper.setRoomOfDate(roomRepoPO) <= 0) {
                roomRepoMapper.addRoomOfDate(roomRepoPO);
            }
            fromDate = fromDate.plusDays(1);
        }
        return true;

    }


    @Override
    public Integer getSumOfAvailableNumOfPeriod(Integer hotelId, String fromDate, String endDate) {
        LocalDateTime fromDateTime = LocalDateTime.parse(fromDate + " 00:00:00", formatterFull);
        LocalDateTime endDateTime = LocalDateTime.parse(endDate + " 00:00:00", formatterFull);
        if (fromDateTime.isAfter(endDateTime)) return 0;

        List<String> dates = new LinkedList<>();
        for (; !fromDateTime.isAfter(endDateTime); fromDateTime = fromDateTime.plusDays(1))
            dates.add(fromDateTime.format(formatterDay));

        List<HotelDateCntPO> roomCntOfHotelOfDates = roomRepoMapper.getRoomCntOfHotelOfDates(hotelId, dates);
        if (roomCntOfHotelOfDates.size() < dates.size()) return 0;

        int suppliedRoom = roomCntOfHotelOfDates.get(0).getCnt();
        for (HotelDateCntPO h : roomCntOfHotelOfDates) {
            suppliedRoom = Math.min(h.getCnt(), suppliedRoom);
        }
        return suppliedRoom;
    }

    @Override
    public List<RoomTypeDetailVO> getCompleteInfoOfPeriod(DatePeriodVO datePeriodVO) {
        List<RoomTypeDetailVO> roomTypeDetailVOS = new ArrayList<RoomTypeDetailVO>();
        Integer roomId = datePeriodVO.getRoomId();
        HotelRoom hotelRoom = roomService.getRoomById(roomId);
        RoomType roomType = hotelRoom.getRoomType();//不确定
        Integer hotelId=  hotelRoom.getHotelId();


        Map<String, Integer> periodInfo = this.getForPeriod(datePeriodVO);
        for(Map.Entry<String,Integer> entry:periodInfo.entrySet()){
            String date  = entry.getKey();
            Integer availableNum = entry.getValue();
            Integer orderedNum  = 0;
            //找到已经预定的roomId数
            Integer orderedNumOfThisRoomType = orderService.getOrderedNumOfThisRoomType(roomType, date, hotelId);
            roomTypeDetailVOS.add(new RoomTypeDetailVO(date,availableNum,orderedNumOfThisRoomType));
        }

        return roomTypeDetailVOS;
    }

    @Override
    public ResponseVO SetAvailableRoomNum(RoomTypeUpdateVO roomTypeUpdateVO) {
        String date = roomTypeUpdateVO.getDate();
        Integer roomId= roomTypeUpdateVO.getRoomId();
        Integer newVal = roomTypeUpdateVO.getNewValue();
        RoomRepoPO roomRepoPO = new RoomRepoPO();

        roomRepoPO.setRoomId(roomId);
        roomRepoPO.setDate(date);
        roomRepoPO.setCurrentNum(newVal);
        if (roomRepoMapper.setRoomOfDate(roomRepoPO) <= 0) {
            roomRepoMapper.addRoomOfDate(roomRepoPO);
        }


        return ResponseVO.buildSuccess(true);
    }

    @Override
    public int getAvailableOfRoomIdAndDate(Integer roomId, String date) {
        return roomRepoMapper.getAvailableOfRoomIdAndDate(roomId,date);
    }

    @Override
    public int setAvailableOfRoomIdAndDate(Integer roomId, String date, int newValue) {
        return roomRepoMapper.setAvailableOfRoomIdAndDate(roomId,date,newValue);
    }
    //offset如果是正的 增加库存 如果是负的 减少库存
    @Override
    public void updateAvailableOfRoomIdAndDates(Integer roomId,String startDateStr,String endDateStr,int offset){
        LocalDateTime startDate = LocalDateTime.parse(startDateStr+ " 00:00:00",formatterFull);
        LocalDateTime endDate = LocalDateTime.parse(endDateStr+ " 00:00:00",formatterFull);
        LocalDateTime currentDate = startDate;
        while(!currentDate.isAfter(endDate)){
            String tempDateStr = currentDate.format(formatterDay);
            int beforeAvailable = getAvailableOfRoomIdAndDate(roomId,tempDateStr);
            int rowNum = setAvailableOfRoomIdAndDate(roomId,tempDateStr,beforeAvailable+offset);
            currentDate =currentDate.plusDays(1);
        }

    }

}
